﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.IO;

namespace tank
{
    enum _Orientation
    {
        Up,
        Down,
        Left,
        Right
    }

    public partial class Form1 : Form
    {
        Panel panel;
        Timer timer;
        public const int SizeX = 20;
        public const int SizeY = 14;
        public const int Side = 48;
        float[,] field = new float[21, 15];
        bool IsMoving;

        Button
            about,
            back,
            startButton,
            exitButton;
        Label label = new Label();
        Label label2 = new Label();
        Label label3 = new Label();

        Graphics graphics;
        BufferedGraphics bufferedGraphics;
        BufferedGraphicsContext bufferedgraphicsContext;

        _Hero
            player1;

        List<_Enemy> enemys;

        List<_Block> blocks;

        List<_Hero> heroes;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ClientSize = new System.Drawing.Size(SizeX * Side + 10, SizeY * Side + 10);

            panel = new Panel()
            {
                Location = new Point(5, 5),
                Size = new Size(ClientSize.Width - 10, ClientSize.Height - 10),
            };
            Controls.Add(panel);

            int x = panel.Width / 2 - 50, y = panel.Height / 2 - 30;

            startButton = new Button()
            {
                Location = new Point(x, y),
                Size = new Size(100, 25),
                Text = "Start"
            };
            startButton.Click += new EventHandler(startButton_Click);

            y += 40;

            exitButton = new Button()
            {
                Location = new Point(x, y),
                Size = startButton.Size,
                Text = "Exit"
            };
            exitButton.Click += new EventHandler(exitButton_Click);

            y += 40;

            about = new Button()
            {
                Location = new Point(x, y),
                Size = startButton.Size,
                Text = "About"
            };
            about.Click += new EventHandler(about_Click);

            panel.Controls.AddRange(new Control[] { startButton, exitButton, about });

            timer = new Timer();
            timer.Interval = 25;
            timer.Tick += new EventHandler(Update);

            enemyStartRect = new Rectangle[3]
            {
                new Rectangle(Side,96,32,32),
                new Rectangle(panel.Width/2-24,Side,32,32),
                new Rectangle(panel.Width-100,Side,32,32)
            };
            label.Visible = label2.Visible = label3.Visible = false;
            InitializeGraphics();
        }

        int timerForNewEnemy;
        int timeMove;
        void Update(object sender, EventArgs e)
        {
            if (heroes.Count == 0 || blocks[blocks.Count - 1].life < 1 || enemys.Count == 0)
            {
                panel.Hide();
                timer.Stop();
                Label label = new Label();
                if (heroes.Count == 0 || blocks[blocks.Count - 1].life < 1)
                { label.Text = "Game Over"; }
                else { label.Text = "You Win"; }
                label.Location = new Point((this.Width - label.Width) / 2, (this.Height - label.Height) / 2);
                Controls.Add(label);
            }
            //player1.Update(ref blocks, ref enemys);
            foreach (_Hero hero in heroes)
            {
                player1.Update(ref blocks, heroes, ref enemys);
            }
            //foreach (_Enemy enemy in enemys)
            IsMoving = true;
            if (timeMove > 10)
            {
                timeMove = 0;
                IsMoving = false;
            }
            timeMove++;
            for (int i = 0; i < enemys.Count; i++ )
            {
                enemys[i].Update(ref blocks, ref heroes, enemys, IsMoving);
                DrawToBuffer();

                timerForNewEnemy++;
                if (timerForNewEnemy == 100 && enemys.Count <= 2)
                {
                    timerForNewEnemy = 0;
                    Point point = EnemyStartPosition();
                    if (point.X != 0)
                        enemys.Add(new _Enemy(point, panel.Width, panel.Height, field));
                }
            }
        }
        Rectangle[] enemyStartRect;
        int currentEnemyStartPoint;
        Point EnemyStartPosition()
        {
            Point point;

            if (TestStartPoint())
            {
                currentEnemyStartPoint++;
                if (currentEnemyStartPoint == 3)
                    currentEnemyStartPoint = 0;
                if (TestStartPoint())
                {
                    currentEnemyStartPoint++;
                    if (currentEnemyStartPoint == 3)
                        currentEnemyStartPoint = 0;
                    if (TestStartPoint())
                    {
                        currentEnemyStartPoint++;
                        if (currentEnemyStartPoint == 3)
                            currentEnemyStartPoint = 0;
                        point = new Point(0, 0);
                    }
                    else point = enemyStartRect[currentEnemyStartPoint].Location;
                }
                else point = enemyStartRect[currentEnemyStartPoint].Location;
            }
            else point = enemyStartRect[currentEnemyStartPoint].Location;

            currentEnemyStartPoint++;
            if (currentEnemyStartPoint == 3)
                currentEnemyStartPoint = 0;

            return point;
        }

        bool TestStartPoint()
        {
            bool intersect = false;
            foreach (_Enemy enemy in enemys)
            {
                if (RectIntersect(enemyStartRect[currentEnemyStartPoint], new Rectangle(enemy.Location, enemy.Size)))
                    intersect = true;
            }

            return intersect;
        }

        private void DrawToBuffer()
        {
            bufferedGraphics.Graphics.Clear(Color.White);

            foreach (_Block block in blocks)
            {
                block.Draw(bufferedGraphics.Graphics);
            }

            player1.Draw(bufferedGraphics.Graphics);
            foreach (_Enemy enemy in enemys)
            {
                enemy.Draw(bufferedGraphics.Graphics);
            }

            bufferedGraphics.Render();
        }

        public void InitializeGraphics()
        {
            graphics = panel.CreateGraphics();
            bufferedgraphicsContext = new BufferedGraphicsContext();
            bufferedGraphics = bufferedgraphicsContext.Allocate(graphics, new Rectangle(0, 0, panel.Width, panel.Height));
        }

        public void startButton_Click(object sender,EventArgs e)
        {
            CreateLevel(1);
            about.Enabled = about.Visible = startButton.Enabled = startButton.Visible = exitButton.Enabled = exitButton.Visible = false;
            heroes = new List<_Hero>();
            player1 = new _Hero(new Point(7*48, 11*48), panel.Width, panel.Height);
            heroes.Add(player1);
            enemys = new List<_Enemy>();
            _Enemy enemy = new _Enemy(new Point(50, 50), panel.Width, panel.Height, field);
            enemys.Add(enemy);



            timer.Start();
        }

        public void exitButton_Click(object sender,EventArgs e)
        {
            Application.Exit();
        }
        public void about_Click(object sender, EventArgs e)
        {
            panel.Hide();
            label.Visible = true; label2.Visible = true; label3.Visible = true;
            label.AutoSize = true;
            label2.AutoSize = true;
            label3.AutoSize = true;
            label.Text = "ОСНОВЫ АЛГОРИТМИЗАЦИИ И ПРОГРАММИРОВАНИЯ";
            label2.Text = "Программа разработана в качастве курсовой работы";
            label3.Text = "Выполнил студент гр. РИС-11 Секерин Е.А. 2012 г";
            label.Location = new Point((this.Width - label.Width) / 2 - 50, (this.Height - label.Height) / 2 - 50);
            label3.Location = label2.Location = label.Location;
            label2.Top = label.Top + 50;
            label3.Top = label2.Top + 50;
            Controls.Add(label);
            Controls.Add(label2);
            Controls.Add(label3);
            back = new Button()
            {
                Location = new Point(label3.Right - label3.Width, label3.Top + 50),
                Size = startButton.Size,
                Text = "Back"
            };
            back.Click += new EventHandler(Form1_Load);
            Controls.Add(back);
        }
        protected override void OnKeyDown(KeyEventArgs e)
        {
            e.SuppressKeyPress = true;
            switch (e.KeyCode)
            {
                case Keys.W:
                    {
                        StartRun(player1, _Orientation.Up);
                        break;
                    }

                case Keys.S:
                    {
                        StartRun(player1, _Orientation.Down);
                        break;
                    }

                case Keys.A:
                    {
                        StartRun(player1, _Orientation.Left);
                        break;
                    }

                case Keys.D:
                    {
                        StartRun(player1, _Orientation.Right);
                        break;
                    }

                case Keys.Space:
                    {
                        //if (!player1.Bullet.IsRunning)
                            player1.StartShoot();
                        break;
                    }
            }

            base.OnKeyDown(e);
        }

        protected override void OnKeyUp(KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.W:
                case Keys.S:
                case Keys.A:
                case Keys.D:
                    {
                        player1.IsRunning = false;
                        break;
                    }
            }

            base.OnKeyUp(e);
        }

        /// <summary>
        /// старт движения игрока
        /// </summary>
        /// <param name="player"> игрок </param>
        /// <param name="orientation"> направление </param>
        void StartRun(_Hero player, _Orientation orientation)
        {
            player.IsRunning = true;
            player.Or = orientation;
        }

        public void CreateLevel(int level)
        {
            blocks = new List<_Block>();
            string levelFilePath = @"levels/level" + level + ".txt";
            string[] fileStr = File.ReadAllLines(levelFilePath);
            _Block block;
            int x=0,y=0;
            foreach (string s in fileStr)
            {
                foreach (char c in s)
                {
                     block = new _Block(new Point(x, y), _BlockType.Place_Green, 0);
                        blocks.Add(block);
                    switch (c)
                    {
                        case '1':
                        block = new _Block(new Point(x, y), _BlockType.Brick_Box_Def, 1);
                        blocks.Add(block);
                        field[(int)(x / Side), (int)(y / Side)] = 0;
                        break;
                        case 'R':
                        block = new _Block(new Point(x, y), _BlockType.Brick_Box_Red, 2);
                        blocks.Add(block);
                        field[(int)(x / Side), (int)(y / Side)] = 0;
                        break;
                        case '9':
                        block = new _Block(new Point(x, y), _BlockType.Brick_Box_Iron, 0);
                        blocks.Add(block);
                        field[(int)(x / Side), (int)(y / Side)] = 0;
                        break;
                        default: field[(int)(x / Side), (int)(y / Side)] = 10; break;
                    }
                    //System.Diagnostics.Debug.Write(field[(int)(x / Side), (int)(y / Side)] + " ");
                    x += Side;
                }
                x = 0;
                y += Side;
                //System.Diagnostics.Debug.Write("\n");
            }
            block = new _Block(new Point(9 * Side + 24, 12 * 48 - 24), _BlockType.Base, 6);
            blocks.Add(block);
            field[9, 12] = 100;
            field[10, 12] = 100;
            field[9, 13] = 100;
            field[10, 13] = 100;
        }


        bool RectIntersect(Rectangle rect1, Rectangle rect2)
        {
            bool intersect = false;

            if (rect1.Left >= rect2.Left && rect1.Left <= rect2.Right && rect1.Top >= rect2.Top && rect1.Top <= rect2.Bottom
               || rect1.Left >= rect2.Left && rect1.Left <= rect2.Right && rect1.Bottom >= rect2.Top && rect1.Bottom <= rect2.Bottom
               || rect1.Right >= rect2.Left && rect1.Right <= rect2.Right && rect1.Top >= rect2.Top && rect1.Top <= rect2.Bottom
               || rect1.Right >= rect2.Left && rect1.Right <= rect2.Right && rect1.Bottom >= rect2.Top && rect1.Bottom <= rect2.Bottom)
                intersect = true;

            return intersect;
        }
    }
}
